home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
forth
/
amiga
/
s4th68k.arc
/
SFORTH.68K
Wrap
Text File
|
1987-11-08
|
43KB
|
2,225 lines
;
; Sforth for the 68000.
;
; Created by Alan DeMars, Scorpion Softworks, 1/1/87.
;
; The FORTH processor has been eliminated. All calls to FORTH words
; are done explicitly with JSR's.
;
; The standard FIG FORTH word headers have been retained.
;
; The 'COMPILE' command compiles 3 words. The 1st
; word is always '4EB9' ( JSR ) the last 2 are the absolute address.
;
; The SMUDGE bit has been replaced by the MACRO bit. If set, the word's
; code is copied into new word definitions (instead of compiling a JSR
; to the CFA). Use like IMMEDIATE. Just write MACRO immediately after a
; word's definition if you want its code to be copied inline to a new
; word's code field. Everything up to the 'RTS' ($4E75) gets copied.
;
; Anyone is welcome to use this program for any purpose they like.
; However, it would be a great ego boost if you would reference my name
; in your application somewhere (and send me $20.00 for my troubles if
; you feel guilty about getting something for next to nothing).
;
; Also, if you make any modifications like fix any bugs you find or add
; any neat features or if you have any suggestions at all please let me
; know what they are so I can take advantage of your efforts.
;
; My Address:
; 335 South 'H' Street
; Lompoc, California, 93436
;
; I can be reached at (805) 735-1595 between 5pm and 8pm PST.
;
; One more thing: Sforth for the 6809 is also available if you have
; any interest.
;
far code
far data
;
; MACROS for creating dictionary headers
;
; The assembler I'm using doesn't have a SET directive so I can't
; thread the words together with the WORDM macro. Instead I compile
; a (unique) long word of $ad55ad55 in the link field of each header
; and thread the words together at cold start.
;
; for single character words
MACRO WORDM1
dc.b $81,$80+'%3'
dc.l $ad55ad55
ENDM
; for multiple character words
MACRO WORDMX
dc.b $80+%1,"%2",$80+'%3'
dc.l $ad55ad55
ENDM
; for single character immediate words
MACRO WORDMI1
dc.b $C1,$80+'%3'
dc.l $ad55ad55
ENDM
; for multiple character immediate words
MACRO WORDMIX
dc.b $C0+%1,"%2",$80+'%3'
dc.l $ad55ad55
ENDM
; for single character MACRO words
MACRO WORDMM1
dc.b $A1,$80+'%3'
dc.l $ad55ad55
ENDM
; for multiple character MACRO words
MACRO WORDMMX
dc.b $A0+%1,"%2",$80+'%3'
dc.l $ad55ad55
ENDM
; for USER variables
MACRO WORDMU
dc.b $80+%1,"%2",$80+'%3'
dc.l $ad55ad55
%4 JSR DOUSER
dc.l %5-UBEGIN
ENDM
;
; THE DO MACROS
;
; These Macros simply make a long list of JSR's easier to write
; by allowing you to write all the calls on one line.
;
; Example:
;
; DO4 LIST,PFIND,ENCLOS,QUIT
;
; Which would expand to:
;
; JSR LIST-START(a4)
; JSR PFIND-START(a4)
; JSR ENCLOS-START(a4)
; JSR QUIT-START(a4)
;
; They do tend to slow up the assembly process though.
;
; All words within the kernel use a4 relative addressing to save room.
; All words defined outside the kernel use 32 bit absolute addressing.
;
MACRO DO1
JSR %1-START(a4)
ENDM
MACRO DO2
JSR %1-START(a4)
JSR %2-START(a4)
ENDM
MACRO DO3
JSR %1-START(a4)
JSR %2-START(a4)
JSR %3-START(a4)
ENDM
MACRO DO4
JSR %1-START(a4)
JSR %2-START(a4)
JSR %3-START(a4)
JSR %4-START(a4)
ENDM
MACRO DO5
JSR %1-START(a4)
JSR %2-START(a4)
JSR %3-START(a4)
JSR %4-START(a4)
JSR %5-START(a4)
ENDM
MACRO DO6
JSR %1-START(a4)
JSR %2-START(a4)
JSR %3-START(a4)
JSR %4-START(a4)
JSR %5-START(a4)
JSR %6-START(a4)
ENDM
MACRO DO7
JSR %1-START(a4)
JSR %2-START(a4)
JSR %3-START(a4)
JSR %4-START(a4)
JSR %5-START(a4)
JSR %6-START(a4)
JSR %7-START(a4)
ENDM
MACRO DO8
JSR %1-START(a4)
JSR %2-START(a4)
JSR %3-START(a4)
JSR %4-START(a4)
JSR %5-START(a4)
JSR %6-START(a4)
JSR %7-START(a4)
JSR %8-START(a4)
ENDM
MACRO DO9
JSR %1-START(a4)
JSR %2-START(a4)
JSR %3-START(a4)
JSR %4-START(a4)
JSR %5-START(a4)
JSR %6-START(a4)
JSR %7-START(a4)
JSR %8-START(a4)
JSR %9-START(a4)
ENDM
MACRO DOX
JMP %1-START(a4)
ENDM
;
; Start of user variables.
;
; Some of the next stuff is initialized during COLD and WARM
; starts. Names correspond to FORTH words of similar (no X)
; name.
; below initialized on cold start
bss UBEGIN,0 start of user variables
bss XFENCE,4 fence for FORGET
bss XDP,4 dictionary pointer
bss XVOCL,4 vocabulary listing
bss XEFUNC,4 address of EFUNC driver
bss XDELAY,4 carriage return delay count (# nulls)
bss XCOLUM,4 carriage width
bss XBLK,4 disc block being accessed
bss XIN,4 scan pointer into the block
bss XOUT,4 cursor positionx
bss XSCR,4 disc screen being accessed (0=terminal)
bss XOFSET,4 disc sector offset for multi-disc
bss XCONT,4 last word in primary search vocabulary
bss XCURR,4 last word in extensible vocabulary
bss XSTATE,4 flag for 'interpret' or 'compile' modes
bss XBASE,4 number base for i/o numeric conversioTE
bss XDPL,4 decimal point place
bss XFLD,4
bss XCSP,4 current stack position, for compile checks
bss XRNUM,4
bss XHLD,4
; init below on cold or warm
bss XSPZER,4 initial top of data stack for this user
bss XTIB,4 start of terminal input buffer
bss XRZERO,4 initial top of return stack
bss XFINA,4 address of input file FCB
bss XFOUTA,4 address of output file FCB
bss XWIDTH,4 name file width
bss XMSGBS,4 Base SCReen number for messages and GO
bss XWARN,4 warning message mode (0=no disc)
bss XQUIET,4 echo flag during downloads
bss XIRQV,4 redirectable IRQ vector
bss XFIRQV,4 redirectable FIRQ vector
bss XNMIV,4 redirectable NMI vector
bss XSWIV,4 redirectable SWI vector
bss XSWI2V,4 redirectable SWI2 vector
bss XSWI3V,4 redirectable SWI3 vector
bss XUVPTR,4 User variable pointer
bss XBOOTV,4 User boot word's CFA
bss XEMIT,4 Redirectable EMIT
bss XKEY,4 Redirectable KEY
bss XQTERM,4 Redirectable ?TERMINAL
bss RETURN,4 a7 address at start up
; end of user table
;
; Beginning of variable dictionary entries
;
bss FORTHS,10
bss FORTH,16
bss TASKAA,12
;FORTHS dc.b $C5,"FORT",$80+'H' ; (6 bytes)
; dc.l NOOP-10 ; LINK "BACK" (4 bytes)
;FORTH DO1 DODOES ; (4 bytes)
; dc.l DOVOC ; (4 bytes)
; dc.w $81A0 ; (2 bytes)
; dc.l TASKAA ; (4 bytes)
; dc.w 0 ; (2 bytes)
;TASKAA dc.b $84,"TAS",$80+'K' ; (5+1 bytes)
; dc.l FORTHS ; link "back" to FORTH (4 bytes)
; RTS ; (2 bytes)
; To adjust the user dictionary size change the following entry
bss USRDIC,2048 user dictionary & data stack (might be a little small)
bss DSTACK,256
bss RSTACK,0 return stack
bss TIPBUF,128 terminal input buffer
; Code Segment
cseg
;
; The FORTH program begins here
;
mlist
public _Sforth
START
BRA COLD ;;; Cold Start Entry ;;;
BRA WARM ;;; Warm Start Entry ;;;
;
; Startup parameters
;
; the following is used to initialize the user area on
; cold start only
FENCIN DC.L TASKAA initial fence at task
DPINIT DC.L USRDIC cold start value for DP location in dict.
VOCINT DC.L FORTH+9 cold start for VOC-LINK
EFUNC DC.L $FBEA address of EFUNC
DELINT DC.L 0 initial carriage return delay
COLINT DC.L 80 initial terminal carriage width
ZBLK DC.L 1 disc block being accessed
ZIN DC.L 2 scan pointer into the block
ZOUT DC.L 2 cursor positionx
ZSCR DC.L 0 disc screen being accessed (0=terminal)
ZOFSET DC.L 0 disc sector offset for multi-disc
ZCONT DC.L TASKAA last word in primary search vocabulary
ZCURR DC.L TASKAA last word in extensible vocabulary
ZSTATE DC.L 0 flag for 'interpret' or 'compile' modes
ZBASE DC.L 10 number base for i/o numeric conversions
ZDPL DC.L 2 decimal point place
ZFLD DC.L 0
ZCSP DC.L 0 current stack position, for compile checks
ZRNUM DC.L 0
ZHLD DC.L 0
; end of cold start initialization area
; the following is used to initialize the user area on
; warm or cold start
SINIT DC.L DSTACK initial top of data stack
TIBINT DC.L TIPBUF terminal input buffer
RINIT DC.L RSTACK initial top of return stack
FINA DC.L 0 initialize no input file FCB
FOUTA DC.L 0 initialize no output file FCB
WIDINT DC.L 31 init name field width
MSGBAS DC.L 20 init base SCReen number for messages and GO
WRNINT DC.L 0 init warning mode (0=no disc)
ZQUIET DC.L 0 echo flag during downloads
ZIRQV DC.L 0 redirectable IRQ vector
ZFIRQV DC.L 0 redirectable FIRQ vector
ZNMIV DC.L WARM redirectable NMI vector
ZSWIV DC.L 0 redirectable SWI vector
ZSWI2V DC.L 0 redirectable SWI2 vector
ZSWI3V DC.L 0 redirectable SWI3 vector
ZUVPTR DC.L XHLD+4 User variable pointer
ZBOOTV DC.L 0 User boot word's CFA
ZEMIT DC.L EMITX Redirectable EMIT
ZKEY DC.L KEYX Redirectable KEY
ZQTERM DC.L QTERMX Redirectable ?TERMINAL
UEND
; end warm + cold initialization area
_Sforth
move.l a7,RETURN save for BYE
bra.s COLD
WORDMX 4,COL,D
COLD movea.l RINIT,a7 lets get this straight right up front
; move cold and warm start constants into ram
movea.l #FENCIN,a0
movea.l #XFENCE,a1
COLD40 move.b (a0)+,(a1)+
cmpi.l #UEND,a0
bne.s COLD40
; move 'FORTH' and 'TASK' to ram
movea.l #RAM,a0
movea.l #FORTHS,a1
COLD50 move.b (a0)+,(a1)+
cmpi.l #ERAM,a0
bne.s COLD50
; fill in link field pointers.
move.l #START,a0
move.l #0,a1 ; last link field points to null
COLD60 cmpa.l #NOOP,a0 ; at end of dictionary?
bhi.s COLD90
cmpi.w #$ad55,(a0)+ ; found 1st half?
bne.s COLD60 ; no
; maybe
cmpi.w #$ad55,(a0)+ ; found second half?
bne.s COLD60 ; no
subq.l #4,a0 ; a0 points to link field
move.l a1,(a0) ; point to previous word's NFA
move.l a0,a1
COLD70 tst.b -(a1) ; back up to end of nfa
bpl.s COLD70 ; only if name ended on even byte
COLD80 tst.b -(a1) ; back up to start of nfa
bpl.s COLD80
bra.s COLD60 ; a1 is now pointing to this words nfa
; misc.
COLD90 movea.l XSPZER,a6 initial parameter stack
movea.l #START,a4 base address of FORTH
JSR UCOLD user cold start
JSR UWARM user warm start
DOX ABORT go to ABORT if no user auto-start
WORDMX 4,WAR,M
WARM movea.l XRZERO,a7 initial return stack
; Initialize warmstart variables
movea.l #SINIT,a0
movea.l #XSPZER,a1
WARM10 move.l (a0)+,(a1)+
cmpi.l #UEND,a0
bne.s WARM10
movea.l XSPZER,a6 initial parameter stack
movea.l #START,a4 base address of FORTH
DO1 UWARM do user warm start
DOX ABORT
WORDMI1 1,,:
COLON DO6 QEXEC,SCSP,CURENT,AT,CONTXT,STORE
DO2 CREATE,LIT
DC.L -6 ; create advances HERE 6 too far
DO2 ALLOT,RBRAK
rts
WORDMI1 1,,;
SEMI DO2 QCSP,WLITER
DC.W $4E75 rts
DO1 WCOMM
DOX LBRAK
WORDMX 2,;,S
SEMIS addq.l #4,a7
rts
WORDMX 7,EXECUT,E
EXEC movea.l (a6)+,a0
jmp (a0)
WORDMX 3,MO,N
MON jmp PMON
WORDMX 3,BY,E
BYE movea.l RETURN,a7
rts
WORDMX 3,JS,R
JSR movea.l (a6)+,a0
jmp (a0)
WORDMX 4,EMI,T
EMIT movea.l XEMIT,a0
jmp (a0) ; to current EMIT handler
EMITX move.l (a6)+,d0
jsr PEMIT
addq.l #1,XOUT
rts
WORDMX 3,KE,Y
KEY movea.l XKEY,a0
jmp (a0) ; to current KEY handler
KEYX jsr PKEY
move.l d0,-(a6)
rts
WORDMX 9,?TERMINA,L
QTERM movea.l XQTERM,a0
jmp (a0) ; to current ?TERMINAL handler
QTERMX jsr PQTER
move.l d0,-(a6)
rts
WORDMX 2,C,R
CR DO2 QTERM,ZBRAN
dc.w CR1-START
DO1 QUIT
CR1 DO1 WLITER
dc.w $0A
DO2 EMIT,WLITER
dc.w $0D line feed
DO5 EMIT,ZERO,OUT,STORE,LIT
dc.l XDELAY
DO2 AT,ZBRAN
dc.w CRE-START
DO1 LIT
dc.l XDELAY
DO3 AT,ZERO,XDO
CR2 DO3 ZERO,EMIT,XLOOP
dc.w CR2-START
CRE rts
WORDMX 3,SP,@
SPAT movea.l a6,a0 ; get current value of parameter stack pointer
move.l a0,-(a6)
rts
WORDMX 3,SP,!
SPSTOR movea.l XSPZER,a6
rts
WORDMX 3,RP,!
RPSTOR movea.l (a7),a0 ; save return address in a0
movea.l XRZERO,a7 ; initialize return stack ptr from constant
jmp (a0) ; return like an rts
WORDMX 3,LI,T
LIT movea.l (a7)+,a0 ; return address points to literal
move.l (a0)+,-(a6)
jmp (a0)
WLITER movea.l (a7)+,a0 ; return address points to literal
move.w (a0)+,d0
ext.l d0
move.l d0,-(a6)
jmp (a0)
;
; These are the branches used within the kernel. They use
; a4 relative addressing. a4 points to the base of the kernel
;
BRAN bra.s ZBYES ; go steal code in ZBRANCH
ZBRAN move.l (a6)+,d0 ; get quantity on stack and drop it
bne.s ZBNO
ZBYES movea.l (a7)+,a0 ; return addr pts to a4 relative offset
movea.w (a0),a1 ; get offset into a1
jmp 0(a4,a1.w) ; take branch
ZBNO movea.l (a7)+,a0 ; return addr pts to offset
jmp 2(a0) ; jmp over it
;
; These are the (LOOP) and (+LOOP) used within the kernel. They use
; a4 relative addressing. a4 points to the base of the kernel
;
XLOOP moveq.l #1,d0 ; set inc cntr to 1
bra.s XPLOP2 ; and steal other code
XPLOOP move.l (a6)+,d0 ; remove step from stack
XPLOP2 bpl.s XPLOF ; forward loopint
add.l 4(a7),d0 ; add step to index
move.l d0,4(a7)
cmp.l 8(a7),d0 ; compare with limit
bpl.s ZBYES ; if not there yet (index >= loop)
bra.s XPLONO ; fall thru if index < loop
XPLOF add.l 4(a7),d0 ; add step to index
move.l d0,4(a7)
cmp.l 8(a7),d0 ; compare with limit
bmi.s ZBYES ; if not there yet (index < loop)
; fall thru if index >= loop
XPLONO movea.l (a7)+,a0 ; return address pts to loop branch
addq.l #8,a7 ; drop index & limit from return stack
jmp 2(a0)
;
; These are the branches used outside the kernel. The return address
; points to the offset which is one word in length.
;
WORDMX 6,BRANC,H
BRANCH bra.s ZBYE10
WORDMX 7,0BRANC,H
ZBRANCH move.l (a6)+,d0 ; get quantity on stack and drop it
bne.s ZBNO10
ZBYE10 movea.l (a7)+,a0 ; return addr pts to offset
movea.w (a0),a1 ; get offset into a1
jmp 0(a0,a1.w) ; take branch
ZBNO10 movea.l (a7)+,a0 ; return addr pts to offset
jmp 2(a0) ; jmp over it
;
; These are the (LOOP) and (+LOOP) used outside the kernel.
;
WORDMX 6,(LOOP,)
FLOOP moveq.l #1,d0 ; set inc cntr to 1
bra.s FPLOP2 ; and steal other code
WORDMX 7,(+LOOP,)
FPLOOP move.l (a6)+,d0 ; remove step from stack
FPLOP2 bpl.s FPLOF ; forward loopint
add.l 4(a7),d0 ; add step to index
move.l d0,4(a7)
cmp.l 8(a7),d0 ; compare with limit
bpl.s ZBYE10 ; if not there yet (index >= loop)
bra.s FPLONO ; fall thru if index < loop
FPLOF add.l 4(a7),d0 ; add step to index
move.l d0,4(a7)
cmp.l 8(a7),d0 ; compare with limit
bmi.s ZBYE10 ; if not there yet (index < loop)
; fall thru if index >= loop
FPLONO movea.l (a7)+,a0 ; return address pts to loop branch
addq.l #8,a7 ; drop index & limit from return stack
jmp 2(a0)
WORDMX 4,(DO,)
XDO move.l (a6)+,d0 ; counter
move.l (a6)+,d1 ; limit
movea.l (a7)+,a0 ; pick up return address
move.l d1,-(a7) ; move limit to return stack
move.l d0,-(a7) ; move index to return stack
jmp (a0) ; carry on
wordm1 1,,I
I move.l 4(a7),-(a6) ; move index to parameter stack
rts
WORDM1 1,,J
J move.l 8(a7),-(a6) ; move limit to parameter stack
rts
WORDM1 1,,K
K move.l 12(a7),-(a6) ; get third counter
rts
WORDMX 5,DIGI,T
DIGIT
move.l 4(a6),d0 ; second item is char of interest
subi.l #$30,d0 ; ASCII zero
bmi.s DIGIT2 ; if less than '0', ILLEGAL
cmpi.l #$0A,d0
bmi.s DIGIT0 ; if '9' or less
cmpi.l #$11,d0
bmi.s DIGIT2 ; if less than 'A'
andi.b #%11011111,d0 ; force upper case
cmpi.l #$2B,d0
bpl.s DIGIT2 ; if greater than 'Z'
subq.l #7,d0 ; translate 'A' thru 'Z'
DIGIT0 cmp.l (a6),d0
bpl.s DIGIT2 ; if not less than base
move.l #1,(a6) ; true flag
move.l d0,4(a6)
rts
DIGIT2 lea.l 4(a6),a6 ; pop top off
move.l #0,(a6) ; bad char flag
rts
WORDMX 6,(FIND,)
PFIND
PFND05 movea.l (a6),a0 ; current nfa
movea.l 4(a6),a1 ; start of text string
clr.l d0
clr.l d1
move.b (a0)+,d0 ; get byte count of this words name
move.l d0,d1 ; in case this is the one
and.l #$1f,d0 ; mask non count bits
cmp.b (a1)+,d0 ; are the lengths the same?
bne.s PFND20 ; if not then go find next nfa
bra.s PFND10
PFND08 cmp.b (a0)+,d0
beq.s PFND10
eori.b #%00100000,d0 ; toggle case of character
cmp.b -1(a0),d0 ; and try again
bne.s PFND20
PFND10 move.b (a1)+,d0 ; compare next byte
tst.b (a0) ; dictionary entry negative?
bpl.s PFND08
ori.b #$80,d0 ; make our byte negative too
cmp.b (a0),d0 ; is this it?
beq.s PFND15 ; yes
eori.b #%00100000,d0 ; no, toggle case of character
cmp.b (a0),d0 ; and try again
bne.s PFND20 ; no, try next one
PFND15 move.l a0,d0
addq.l #2,d0 ; align to word boundary
andi.b #$FE,d0 ; round up to even address (link field)
addi.l #10,d0 ; convert to pfa
move.l d0,4(a6) ; copy this pfa to correct place on stack
move.l d1,(a6) ; length of name field
move.l #1,-(a6) ; true
rts
PFND20 btst.b #7,(a0)+ ; find trailing character
beq.s PFND20
move.l a0,d0
addq.l #1,d0 ; align to word boundary
andi.b #$FE,d0 ; round up to even address
move.l d0,a0 ; a0 points to link field
tst.l (a0) ; end of dictionary?
beq.s PFND30 ; yes
move.l (a0),(a6) ; make this the current nfa
bra PFND05 ; and try again
PFND30 addq.l #4,a6 ; drop
move.l #0,(a6) ; false
rts
WORDMX 7,ENCLOS,E
ENCLOS move.l (a6)+,d0 ; delimiter
movea.l (a6),a0 ; start addr of string
clr.l d1
ENCL05 tst.b (a0) ; is char a null?
beq.s ENCL25 ; yes, then it is the delimiter
cmp.b (a0),d0 ; at non delimiter?
bne.s ENCL10
addq.l #1,a0 ; incr pointer
addq.l #1,d1 ; incr byte offset counter
bra.s ENCL05
ENCL10 move.l d1,-(a6) ; push offset to first non delimiter
ENCL15 tst.b (a0) ; next character a null?
beq.s ENCL30 ; yes
cmp.b (a0)+,d0 ; is it the delimiter yet?
beq.s ENCL20
addq.l #1,d1 ; incr byte offset counter
bra.s ENCL15
ENCL20 move.l d1,-(a6) ; push offset to delimiter after word
addq.l #1,d1
move.l d1,-(a6) ; push offset to 1st char not scanned
rts
ENCL25 move.l d1,-(a6)
addq.l #1,d1
move.l d1,-(a6)
subq.l #1,d1
move.l d1,-(a6)
rts
ENCL30 move.l d1,-(a6) ; byte offset of null
move.l d1,-(a6) ; byte offset of null
rts
WORDMX 5,CMOV,E
CMOVE move.l (a6)+,d0
movea.l (a6)+,a1
movea.l (a6)+,a0
subq.l #1,d0 ; for dbra
CMOVE1 move.b (a0)+,(a1)+
dbra d0,CMOVE1
rts
WORDMX 5,WMOV,E
WMOVE move.l (a6)+,d0
movea.l (a6)+,a1
movea.l (a6)+,a0
subq.l #1,d0 ; for dbra
WMOVE1 move.w (a0)+,(a1)+
dbra d0,WMOVE1
rts
WORDMX 4,MOV,E
MOVE move.l (a6)+,d0
movea.l (a6)+,a1
movea.l (a6)+,a0
subq.l #1,d0 ; for dbra
MOVE1 move.l (a0)+,(a1)+
dbra d0,MOVE1
rts
WORDMX 2,U,*
USTAR move.l (a6),d0 ; a0 in lo word of d0
move.l 4(a6),d1
move.l d1,d2
move.l d1,d3
move.l d1,d4
swap d2 ; b1 in lo half of d2
swap d4 ; b1 in lo half of d4
mulu d0,d1 ; a0*b0 = d1
mulu d0,d2 ; a0*b1 = d2
swap d0 ; move a1 to lo word of d0
mulu d0,d3 ; a1*b0 = d3
mulu d0,d4 ; a1*b1 = d4
move.l #0,(a6) ; 0 to msp
move.l d1,4(a6) ; a0*b0
add.l d2,2(a6) ; + a0*b1*2^16
add.l d3,2(a6) ; + a1*b0*2^16
move.l (a6),d5
addx.l d5,d4 ; + a1*b1*2^32
move.l d4,(a6)
rts
WORDMX 2,U,/
USLASH DO2 USLASHM,SWAP
addq.l #4,a6 ; drop
RTS
WORDMX 5,U/MO,D
USLASHM move.l (a6)+,d1
move.l (a6)+,d0
jsr comdivide
move.l d1,-(a6) ; push remainder
move.l d0,-(a6) ; push quotient
rts
comdivide:
movem.l d2/d3,-(sp)
swap d1 ;check high word
tst.w d1 ;check for easy case
bne.s hardldv
swap d1 ;get low word back
clr.w d3
divu d1,d0
bvc.s format
move.w d0,d2
clr.w d0
swap d0
divu d1,d0
move.w d0,d3
move.w d2,d0
divu d1,d0
format:
move.l d0,d1
swap d0
move.w d3,d0
swap d0
clr.w d1
swap d1
movem.l (sp)+,d2/d3
rts
hardldv:
swap d1
clr.l d2 ;clear out top half of dividend
move.l #31,d3 ;set up loop count
hardloop:
asl.l #1,d0
roxl.l #1,d2
sub.l d1,d2 ;subtract divisor till negative
bmi.s zerobit
onebit:
add.l #1,d0 ;set bit in quotient
dbra d3,hardloop
bra.s hard_done
zeroloop:
asl.l #1,d0
roxl.l #1,d2 ;shift dividend left one bit
add.l d1,d2 ;add divisor till positive
bpl.s onebit
zerobit:
dbra d3,zeroloop
add.l d1,d2 ;add divisor in one more time to fix remainder
hard_done:
move.l d2,d1 ;copy remainder
movem.l (sp)+,d2/d3
rts
WORDMMX 3,AN,D
AND move.l (a6)+,d0
and.l d0,(a6)
rts
WORDMMX 2,O,R
OR move.l (a6)+,d0
or.l d0,(a6)
rts
WORDMMX 3,XO,R
XOR move.l (a6)+,d0
eor.l d0,(a6)
rts
WORDMM1 1,,+
PLUS move.l (a6)+,d0
add.l d0,(a6)
rts
WORDM1 1,,-
SUB DO1 MINUS
DOX PLUS
WORDMX 2,D,+
DPLUS move.l (a6)+,d0 ; high part
move.l (a6)+,d1 ; low part
add.l 4(a6),d1 ; add low parts
move.l (a6),d2
addx.l d2,d0 ; add high parts
move.l d0,(a6)
move.l d1,4(a6)
rts
WORDMMX 5,MINU,S
MINUS neg.l (a6)
rts
WORDMMX 6,DMINU,S
DMINUS neg.l (a6)
negx.l 4(a6)
rts
WORDMMX 2,1,+
ONEP addq.l #1,(a6)
rts
WORDMMX 2,2,+
TWOP addq.l #2,(a6)
rts
WORDMMX 2,4,+
FOURP addq.l #4,(a6)
rts
WORDMMX 2,1,-
ONEM subq.l #1,(a6)
rts
WORDMMX 2,2,-
TWOM subq.l #2,(a6)
rts
WORDMMX 2,4,-
FOURM subq.l #4,(a6)
rts
WORDMMX 2,2,*
TWOSTAR move.l (a6),d0
lsl.l #1,d0
move.l d0,(a6)
rts
WORDMMX 2,4,*
FOURSTAR move.l (a6),d0
lsl.l #2,d0
move.l d0,(a6)
rts
WORDMMX 2,2,/
TWODIV move.l (a6),d0
asr.l #1,d0
move.l d0,(a6)
rts
WORDMMX 2,4,/
FOURDIV move.l (a6),d0
asr.l #2,d0
move.l d0,(a6)
rts
; quick multiply of two 16 bit numbers
WORDMX 2,Q,*
QSTAR move.l (a6)+,d0 ; w/ 32 bit result
move.l (a6)+,d1
muls d0,d1
move.l d1,-(a6)
rts
; multiply two 32 bit numbers
WORDM1 1,,*
STAR DO1 USTAR ; w/ 32 bit result
addq.l #4,a6 ; drop
rts
WORDMX 4,/MO,D
SLMOD move.l (a6)+,d1
move.l (a6)+,d0
move.l d4,-(sp)
clr.l d4 ;mark result as positive
tst.l d0
bpl.s prim_ok
neg.l d0
add.w #1,d4 ;mark as negative
prim_ok:
tst.l d1
bpl.s sec_ok
neg.l d1
eor.w #1,d4 ;flip sign of result
sec_ok:
jsr comdivide
chksign:
tst.w d4
beq.s posres
neg.l d0 ; change sign of quotient
neg.l d1 ; change sign of remainder
posres:
move.l (sp)+,d4
move.l d1,-(a6) ; push remainder
move.l d0,-(a6) ; push quotient
rts
WORDM1 1,,/
SLASH DO2 SLMOD,SWAP
addq.l #4,a6 ; drop remainder
rts
WORDMX 3,MO,D
MOD DO1 SLMOD
addq.l #4,a6 ; drop quotient
rts
WORDMX 2,*,/
SSLASH DO3 TOR,STAR,FROMR
DOX SLASH
WORDMX 5,M/MO,D
MSMOD DO7 TOR,ZERO,R,USLASH,FROMR,SWAP,TOR
DO2 USLASH,FROMR
rts
WORDMX 3,AB,S
ABS DO3 DUP,ZLESS,ZBRAN
dc.w ABS2-START
DOX MINUS
ABS2 rts
WORDMX 4,DAB,S
DABS DO3 DUP,ZLESS,ZBRAN
dc.w DABS2-START
DOX DMINUS
DABS2 rts
WORDM1 1,,<
LESS move.l 4(a6),d0 ; get A
cmp.l (a6)+,d0 ; A - B
blt.s LESS1
move.l #0,(a6) ; not less than
rts
LESS1 move.l #1,(a6)
rts
WORDM1 1,,=
EQUAL DO1 SUB
DOX ZEQU
WORDM1 1,,>
GREAT DO1 SWAP
DOX LESS
WORDMX 2,+,-
SETSN DO2 ZLESS,ZBRAN
dc.w SETSN2-START
DOX MINUS
SETSN2 rts
WORDMX 3,D+,-
DSETSN DO2 ZLESS,ZBRAN
dc.w DSETS2-START
DOX DMINUS
DSETS2 rts
WORDMX 2,0,=
ZEQU tst.l (a6)
beq.s ZEQU10
move.l #0,(a6)
rts
ZEQU10 move.l #1,(a6)
rts
WORDMX 3,NO,T
NOT bra.s ZEQU
WORDMX 2,0,<
ZLESS tst.l (a6)
bmi.s ZLESS10
move.l #0,(a6)
rts
ZLESS10 move.l #1,(a6)
rts
WORDMMX 5,LEAV,E
LEAVE move.l 4(a7),8(a7)
rts
WORDMMX 2,>,R
TOR movea.l (a7),a0
move.l (a6)+,(a7)
jmp (a0)
rts
WORDMMX 2,R,>
FROMR movea.l (a7)+,a0
move.l (a7)+,-(a6)
jmp (a0)
rts
WORDMM1 1,,R
R move.l 4(a7),-(a6)
rts
WORDMMX 4,OVE,R
OVER move.l 4(a6),d0
move.l d0,-(a6)
rts
WORDMMX 4,DRO,P
DROP addq.l #4,a6
rts
WORDMMX 4,SWA,P
SWAP move.l (a6),d0
move.l 4(a6),(a6)
move.l d0,4(a6)
rts
WORDMMX 3,DU,P
DUP move.l (a6),-(a6)
rts
WORDMX 3,RO,T
ROT DO3 TOR,SWAP,FROMR
DOX SWAP
WORDMX 4,PIC,K
PICK move.l (a6),d0
mulu.w #4,d0
move.l 0(a6,d0.l),(a6)
rts
WORDMMX 2,+,!
PSTORE movea.l (a6)+,a0
move.l (a6)+,d0
add.l d0,(a0)
rts
WORDMM1 1,,@
AT movea.l (a6),a0
move.l (a0),(a6)
rts
WORDMX 2,W,@
WAT movea.l (a6),a0
clr.l d0
move.w (a0),d0
move.l d0,(a6)
rts
WORDMX 2,C,@
CAT movea.l (a6),a0
clr.l d0
move.b (a0),d0
move.l d0,(a6)
rts
WORDMM1 1,,!
STORE movea.l (a6)+,a0
move.l (a6)+,(a0)
rts
WORDMMX 2,W,!
WSTORE movea.l (a6)+,a0
move.l (a6)+,d0
move.w d0,(a0)
rts
WORDMMX 2,C,!
CSTORE movea.l (a6)+,a0
move.l (a6)+,d0
move.b d0,(a0)
rts
;
; CREATES: DICTIONARY HEADER
; jsr CON
; dc.l 0
;
WORDMX 7,<BUILD,S
BUILDS DO1 ZERO
DOX CON
;
; CREATES: DICT HEADER
; jsr DODOES
; dc.l ADDRESS1
; ADDRESS2 equ *
;
; WHEN EXECUTED, WILL PLACE ADDRESS2 ON STACK
; THEN EXECUTES CODE AT ADDRESS1
;
WORDMX 5,DOES,>
DOES move.l (a7)+,-(a6) ; move return address (ADDRESS1) to stack
DO4 LATEST,PFA,STORE,PSCODE
DODOES movea.l (a7)+,a0 ; don't return there
lea.l 4(a0),a1 ; point to address2
move.l a1,-(a6) ; place on stack
movea.l (a0),a0 ; get address of handler
jmp (a0) ; jump to address1
WORDMX 6,TOGGL,E
TOGGLE DO4 OVER,CAT,XOR,SWAP
DOX CSTORE
WORDMX 8,CONSTAN,T
CON DO3 CREATE,COMMA,PSCODE
DOCON movea.l (a7)+,a0
move.l (a0),-(a6)
rts
WORDMX 5,TOVA,R
TOVAR bra.s CON
WORDMIX 2,T,O
TO DO4 TICK,STATE,AT,ZBRAN
dc.w TO10-START
DO2 COMPIL,STORE
RTS
TO10 DOX STORE
WORDMX 8,VARIABL,E
VAR DO2 CON,PSCODE
DOVAR move.l (a7)+,-(a6)
rts
WORDMM1 1,,0
ZERO moveq.l #0,d0
move.l d0,-(a6)
rts
WORDMM1 1,,1
ONE moveq.l #1,d0
move.l d0,-(a6)
rts
WORDMM1 1,,2
TWO moveq.l #2,d0
move.l d0,-(a6)
rts
WORDMM1 1,,3
THREE moveq.l #3,d0
move.l d0,-(a6)
rts
WORDMM1 1,,4
FOUR moveq.l #4,d0
move.l d0,-(a6)
rts
WORDMMX 2,B,L
BL moveq.l #$20,d0
move.l d0,-(a6) ; ascii blank
rts
WORDMMX 3,C/,L
CSL moveq.l #80,d0
move.l d0,-(a6)
rts
WORDMMX 5,STAR,T
STRT move.l #START,-(a6)
rts
WORDMX 4,USE,R
USER DO2 CON,PSCODE
DOUSER movea.l (a7)+,a0 ; gets offset to user's table
move.l (a0),d0
add.l #UBEGIN,d0 ; add to users base address
move.l d0,-(a6)
rts
WORDMX 7,+ORIGI,N
PORIG DO1 LIT
dc.l START
DOX PLUS
WORDMX 2,S,0
SZERO DO1 DOUSER
dc.l XSPZER-UBEGIN
WORDMX 2,R,0
RZERO DO1 DOUSER
dc.l XRZERO-UBEGIN
WORDMU 3,TI,B,TIB,XTIB
WORDMU 5,WIDT,H,WIDTH,XWIDTH
WORDMU 7,WARNIN,G,WARN,XWARN
WORDMU 5,FENC,E,FENCE,XFENCE
WORDMU 2,D,P,DPTR,XDP
WORDMU 8,VOC-LIN,K,VOCLIN,XVOCL
WORDMU 3,BL,K,BLK,XBLK
WORDMU 2,I,N,IN,XIN
WORDMU 3,OU,T,OUT,XOUT
WORDMU 3,SC,R,SCR,XSCR
WORDMU 6,OFFSE,T,OFSET,XOFSET
WORDMU 7,CONTEX,T,CONTXT,XCONT
WORDMU 7,CURREN,T,CURENT,XCURR
WORDMU 5,STAT,E,STATE,XSTATE
WORDMU 4,BAS,E,BASE,XBASE
WORDMU 3,DP,L,DPL,XDPL
WORDMU 3,FL,D,FLD,XFLD
WORDMU 3,CS,P,CSP,XCSP
WORDMU 2,R,#,RNUM,XRNUM
WORDMU 3,HL,D,HLD,XHLD
WORDMU 7,COLUMN,S,COLUMS,XCOLUM
WORDMU 4,IRQ,V,IRQV,XIRQV
WORDMU 5,FIRQ,V,FIRQV,XFIRQV
WORDMU 4,NMI,V,NMIV,XNMIV
WORDMU 4,SWI,V,SWIV,XSWIV
WORDMU 5,SWI2,V,SWI2V,XSWI2V
WORDMU 5,SWI3,V,SWI3V,XSWI3V
WORDMU 5,EMIT,V,EMITV,XEMIT
WORDMU 4,KEY,V,KEYV,XKEY
WORDMU 10,?TERMINAL,V,QTERMV,XQTERM
WORDMU 5,QUIE,T,QUIET,XQUIET
WORDMU 5,UVPT,R,UVPTR,XUVPTR
WORDMU 5,BOOT,V,BOOTV,XBOOTV
WORDMU 4,BYE,V,BYEV,RETURN
;
WORDMX 4,HER,E
HERE DO1 DPTR
DOX AT
WORDMX 5,ALLO,T
ALLOT DO1 DPTR
DOX PSTORE
WORDMX 7,WALLIG,N
WALLIGN DO2 ONEP,LIT
dc.l $FFFFFFFE
DOX AND
; WORDM1 1,,,
dc.b $80+1,$80+','
dc.l $ad55ad55
COMMA DO3 HERE,STORE,FOUR
DOX ALLOT
; WORDMX 2,W,,
dc.b $80+2,"W",$80+','
dc.l $ad55ad55
WCOMM DO3 HERE,WSTORE,TWO
DOX ALLOT
; WORDMX 2,C,,
dc.b $80+2,"C",$80+','
dc.l $ad55ad55
CCOMM DO3 HERE,CSTORE,ONE
DOX ALLOT
WORDMX 5,SPAC,E
SPACE DO1 BL
DOX EMIT
WORDMX 3,MI,N
MIN DO4 OVER,OVER,GREAT,ZBRAN
dc.w MIN2-START
DO1 SWAP
MIN2 addq.l #4,a6 drop
rts
WORDMX 3,MA,X
MAX DO4 OVER,OVER,LESS,ZBRAN
dc.w MAX2-START
DO1 SWAP
MAX2 addq.l #4,a6
rts
WORDMX 4,-DU,P
DDUP DO2 DUP,ZBRAN
dc.w DDUP2-START
DOX DUP
DDUP2 rts
WORDMX 8,TRAVERS,E
TRAV DO1 SWAP
TRAV2 DO3 OVER,PLUS,WLITER
dc.w $7F
DO4 OVER,CAT,LESS,ZBRAN
dc.w TRAV2-START
DO2 SWAP,DROP
TRAV3 rts
WORDMX 6,LATES,T
LATEST DO2 CURENT,AT
DOX AT
WORDMX 3,LF,A
LFA DO1 WLITER
dc.w 10
DOX SUB
WORDMX 3,CF,A
CFA DO1 WLITER
dc.w 6
DOX SUB
WORDMX 3,NF,A
NFA DO1 WLITER
dc.w 11 ; 6 byte cf, 4 byte lf
DO4 SUB,DUP,CAT,WLITER
dc.w $80
DO2 LESS,ZBRAN
dc.w NFA10-START
DO1 ONEM
NFA10 DO2 ONE,MINUS
DOX TRAV
WORDMX 3,PF,A
PFA DO5 ONE,TRAV,ONEP,WALLIGN,WLITER
dc.w 10
DOX PLUS
WORDMX 4,!CS,P
SCSP DO2 SPAT,CSP
DOX STORE
WORDMX 6,?ERRO,R
QERR DO2 SWAP,ZBRAN
dc.w QERR2-START
DO2 ERROR,BRAN
dc.w QERR3-START
QERR2 addq.l #4,a6
QERR3 rts
WORDMX 5,?COM,P
QCOMP DO4 STATE,AT,ZEQU,WLITER
dc.w $11
DOX QERR
WORDMX 5,?EXE,C
QEXEC DO3 STATE,AT,WLITER
dc.w $12
DOX QERR
WORDMX 6,?PAIR,S
QPAIRS DO2 SUB,WLITER
dc.w $13
DOX QERR
WORDMX 4,?CS,P
QCSP DO5 SPAT,CSP,AT,SUB,WLITER
dc.w $14
DOX QERR
WORDMX 8,?LOADIN,G
QLOAD DO4 BLK,AT,ZEQU,WLITER
dc.w $16
DOX QERR
WORDMX 6,?STAC,K
QSTACK DO7 SPAT,SZERO,AT,SWAP,LESS,ONE,QERR
DO3 SPAT,HERE,WLITER
dc.w 128 ; want 128 spaces higher than dict
DO4 PLUS,LESS,TWO,QERR ; full stack
rts
WORDMX 7,COMPIL,E
COMPIL DO5 QCOMP,FROMR,DUP,WAT,WLITER
dc.w $4eb9
DO2 EQUAL,ZBRAN
dc.w COMPIL1-START
DO1 WLITER
dc.w $4eb9
DO7 WCOMM,TWOP,DUP,AT,COMMA,FOURP,BRAN
dc.w COMPIL2-START
COMPIL1 DO1 WLITER
dc.w $4ead
DO6 WCOMM,TWOP,DUP,WAT,WCOMM,TWOP
COMPIL2 DOX EXEC
WORDMI1 1,,[
LBRAK DO2 ZERO,STATE
DOX STORE
WORDM1 1,,]
RBRAK DO1 WLITER
dc.w $C0
DO1 STATE
DOX STORE
WORDMX 3,HE,X
HEX DO1 WLITER
dc.w 16
DO1 BASE
DOX STORE
WORDMX 7,DECIMA,L
DEC DO1 WLITER
dc.w 10
DO1 BASE
DOX STORE
WORDMX 7,(;CODE,)
PSCODE move.l (a7)+,-(a6)
DO4 LATEST,PFA,CFA,TWOP ; 2+ moves past JSR opcode in CFA
DOX STORE ; fix Absolute address of JSR
WORDMIX 5,;COD,E
SEMIC DO5 QCSP,COMPIL,PSCODE,LBRAK,QSTACK
; NOTE: QSTACK is replaced by ASSEMBLER in versions with one.
WORDMX 5,COUN,T
COUNT DO3 DUP,ONEP,SWAP
DOX CAT
WORDMX 4,TYP,E
TYPE DO2 DDUP,ZBRAN
dc.w TYPE3-START
DO4 OVER,PLUS,SWAP,XDO
TYPE2 DO4 I,CAT,EMIT,XLOOP
dc.w TYPE2-START
DO1 BRAN
dc.w TYPE4-START
TYPE3 addq.l #4,a6 drop
TYPE4 rts
WORDMX 9,-TRAILIN,G
DTRAIL DO3 DUP,ZERO,XDO
DTRAL2 DO7 OVER,OVER,PLUS,ONE,SUB,CAT,BL
DO2 SUB,ZBRAN
dc.w DTRAL3-START
DO2 LEAVE,BRAN
dc.w DTRAL4-START
DTRAL3 DO2 ONE,SUB
DTRAL4 DO1 XLOOP
dc.w DTRAL2-START
rts
WORDMI1 1,,"
QUOTE DO1 WLITER
dc.w $22 quote
DO3 STATE,AT,ZBRAN
dc.w QUOTE1-START
DO9 COMPIL,PQUOTE,WORD,HERE,CAT,ONEP,WALLIGN,ALLOT,BRAN
dc.w QUOTE2-START
QUOTE1 DO9 WORD,HERE,HERE,CAT,ONEP,PAD,SWAP,CMOVE,PAD
QUOTE2 rts
; WORDMX 3,(",)
dc.b $80+3,'(','"',$80+')'
dc.l $ad55ad55
PQUOTE DO8 R,DUP,CAT,ONEP,FROMR,PLUS,WALLIGN,TOR
rts
; WORDMX 4,(.",)
dc.b $80+3,"(.",'"',$80+')'
dc.l $ad55ad55
PDOTQ DO8 R,COUNT,DUP,ONEP,FROMR,PLUS,WALLIGN,TOR
DOX TYPE
WORDMIX 2,.,"
DOTQ DO1 WLITER
dc.w $22 quote
DO3 STATE,AT,ZBRAN
dc.w DOTQ1-START
DO9 COMPIL,PDOTQ,WORD,HERE,CAT,ONEP,WALLIGN,ALLOT,BRAN
dc.w DOTQ2-START
DOTQ1 DO4 WORD,HERE,COUNT,TYPE
DOTQ2 rts
WORDMX 6,EXPEC,T
EXPECT DO4 OVER,PLUS,OVER,XDO
EXPEC2 DO3 KEY,DUP,WLITER
dc.W $08
DO2 EQUAL,ZBRAN
dc.w EXPEC3-START
addq.l #4,a6 drop
DO1 WLITER
dc.W $08
DO4 OVER,I,EQUAL,DUP
DO7 FROMR,TWO,SUB,PLUS,TOR,SUB,BRAN
dc.w EXPEC6-START
EXPEC3 DO2 DUP,WLITER
dc.w $0D ; (Carriage Return)
DO2 EQUAL,ZBRAN
dc.w EXPEC4-START
DO1 LEAVE
addq.l #4,a6 drop
DO3 BL,ZERO,BRAN
dc.w EXPEC5-START
EXPEC4 DO2 DUP,WLITER
dc.w $09 ; tab
DO2 EQUAL,ZBRAN
dc.w EXPEC1-START
DO2 BL,BRAN
dc.w EXPEC5-START
EXPEC1 DO1 DUP
EXPEC5 DO6 I,CSTORE,ZERO,I,ONEP,CSTORE
EXPEC6 DO3 QUIET,AT,ZBRAN ; no echo if in quiet mode
dc.w EXPEC7-START
addq.l #4,a6 ; drop character
DO1 BRAN
dc.w EXPEC8-START
EXPEC7 DO1 EMIT
EXPEC8 DO1 XLOOP
dc.w EXPEC2-START
addq.l #4,a6 drop
rts
WORDMX 5,QUER,Y
QUERY DO7 TIB,AT,COLUMS,AT,EXPECT,ZERO,IN
DOX STORE
; WORDM1 1,,
dc.b $C1 ; IMMEDIATE
dc.b $80 ; ( NULL)
dc.l $ad55ad55
;ENDM
NULL DO3 BLK,AT,ZBRAN
dc.w NULL2-START
DO9 ONE,BLK,PSTORE,ZERO,IN,STORE,BLK,AT,BSCR
; check for end of screen
DO3 MOD,ZEQU,ZBRAN
dc.w NULL1-START
DO2 QEXEC,FROMR
addq.l #4,a6 drop
NULL1 DO1 BRAN
dc.w NULL3-START
NULL2 DO1 FROMR
addq.l #4,a6 drop
NULL3 rts
WORDMX 4,FIL,L
FILL DO9 SWAP,TOR,OVER,CSTORE,DUP,ONEP,FROMR,ONE,SUB
DOX CMOVE
WORDMX 5,ERAS,E
ERASE DO1 ZERO
DOX FILL
WORDMX 6,BLANK,S
BLANKS DO1 BL
DOX FILL
WORDMX 4,HOL,D
HOLD DO1 LIT
dc.l -1
DO4 HLD,PSTORE,HLD,AT
DOX CSTORE
WORDMX 3,PA,D
PAD DO2 HERE,WLITER
dc.w $44
DOX PLUS
WORDMX 4,WOR,D
WORD DO3 BLK,AT,ZBRAN
dc.w WORD2-START
DO4 BLK,AT,BLOCK,BRAN
dc.w WORD3-START
WORD2 DO2 TIB,AT
WORD3 DO7 IN,AT,PLUS,SWAP,ENCLOS,HERE,WLITER
dc.w 34
DO9 BLANKS,IN,PSTORE,OVER,SUB,TOR,R,HERE,CSTORE
DO4 PLUS,HERE,ONEP,FROMR
DOX CMOVE
; WORDMI1 1,,'
dc.b $80+1,$80+$27 ; single quote
dc.l $ad55ad55
TICK DO4 DFIND,ZEQU,ZERO,QERR
addq.l #4,a6 drop
DOX LITER
WORDMX 6,FORGE,T
FORGET DO6 CURENT,AT,CONTXT,AT,SUB,WLITER
dc.w 24
DO7 QERR,TICK,DUP,FENCE,AT,LESS,WLITER
dc.w 21
DO3 QERR,DUP,LIT
dc.l SINIT
DO3 AT,GREAT,WLITER
dc.w 21
DO9 QERR,DUP,NFA,DPTR,STORE,LFA,AT,CONTXT,AT
DOX STORE
WORDMX 4,BAC,K
BACK DO2 HERE,SUB
DOX WCOMM
WORDMIX 5,BEGI,N
BEGIN DO2 QCOMP,HERE
DOX ONE
WORDMIX 5,ENDI,F
ENDIF DO7 QCOMP,TWO,QPAIRS,HERE,OVER,SUB,SWAP
DOX WSTORE
WORDMIX 4,THE,N
THEN DOX ENDIF
WORDMIX 2,D,O
DO DO3 COMPIL,XDO,HERE
DOX THREE
WORDMIX 4,LOO,P
LOOP DO4 THREE,QPAIRS,COMPIL,FLOOP
DOX BACK
WORDMIX 5,+LOO,P
PLOOP DO4 THREE,QPAIRS,COMPIL,FPLOOP
DOX BACK
WORDMIX 5,UNTI,L
UNTIL DO4 ONE,QPAIRS,COMPIL,ZBRANCH
DOX BACK
WORDMIX 3,EN,D
END DOX UNTIL
WORDMIX 5,AGAI,N
AGAIN DO4 ONE,QPAIRS,COMPIL,BRANCH
DOX BACK
WORDMIX 6,REPEA,T
REPEAT DO7 TOR,TOR,AGAIN,FROMR,FROMR,TWO,SUB
DOX ENDIF
WORDMIX 2,I,F
IF DO5 COMPIL,ZBRANCH,HERE,ZERO,WCOMM
DOX TWO
WORDMIX 4,ELS,E
ELSE DO8 TWO,QPAIRS,COMPIL,BRANCH,HERE,ZERO,WCOMM,SWAP
DO2 TWO,ENDIF
DOX TWO
WORDMIX 5,WHIL,E
WHILE DO1 IF
DOX TWOP
WORDMIX 4,CAS,E
CASE DO5 QCOMP,CSP,AT,SCSP,WLITER
dc.w 4
rts
WORDMIX 2,O,F
OF DO8 FOUR,QPAIRS,COMPIL,OVER,COMPIL,EQUAL,COMPIL,ZBRANCH
DO6 HERE,ZERO,WCOMM,COMPIL,DROP,WLITER
dc.w 5
rts
WORDMIX 5,ENDO,F
ENDOF DO1 WLITER
dc.w 5
DO6 QPAIRS,COMPIL,BRANCH,HERE,ZERO,WCOMM
DO4 SWAP,TWO,ENDIF,FOUR
rts
WORDMIX 7,ENDCAS,E
ENDCASE DO4 FOUR,QPAIRS,COMPIL,DROP
ENDC10 DO6 SPAT,CSP,AT,EQUAL,ZEQU,ZBRAN
dc.w ENDC20-START
DO3 TWO,ENDIF,BRAN
dc.w ENDC10-START
ENDC20 DO2 CSP,STORE
rts
WORDMX 6,SPACE,S
SPACES DO4 ZERO,MAX,DDUP,ZBRAN
dc.w SPACE3-START
DO2 ZERO,XDO
SPACE2 DO2 SPACE,XLOOP
dc.w SPACE2-START
SPACE3 rts
WORDMX 2,<,#
BDIGS DO2 PAD,HLD
DOX STORE
WORDMX 2,#,>
EDIGS addq.l #4,a6 drop
DO4 HLD,AT,PAD,OVER
DOX SUB
WORDMX 4,SIG,N
SIGN DO3 SWAP,ZLESS,ZBRAN
dc.w SIGN2-START
DO1 WLITER
dc.w $2D ; ASCII '-'
DOX HOLD
SIGN2 rts
WORDM1 1,,#
DIG
DO5 BASE,AT,USLASHM,SWAP,WLITER
dc.w 9
DO3 OVER,LESS,ZBRAN
dc.w DIG2-START
DO1 WLITER
dc.w 7
DO1 PLUS
DIG2 DO1 WLITER
dc.w $30 ; ascii zero
DO2 PLUS,HOLD
rts
WORDMX 2,#,S
DIGS
DO4 DIG,DUP,ZEQU,ZBRAN
dc.w DIGS-START
rts
WORDMX 2,.,R
DOTR
DO6 TOR,DUP,ABS,BDIGS,DIGS,SIGN
DO5 EDIGS,FROMR,OVER,SUB,SPACES
DOX TYPE
WORDMX 2,U,.
UDOT DO1 ZERO
DOX DOTR
WORDM1 1,,.
DOT DO2 ZERO,DOTR
DOX SPACE
WORDM1 1,,?
QUEST DO1 AT
DOX DOT
WORDMX 2,W,?
WQUEST DO1 WAT
DOX DOT
WORDMX 2,C,?
CQUEST DO1 CAT
DOX DOT
WORDMX 8,(NUMBER,)
PNUMB
PNUMB1 DO8 ONEP,DUP,TOR,CAT,BASE,AT,DIGIT,ZBRAN
dc.w PNUMB4-START
DO4 SWAP,BASE,AT,USTAR
addq.l #4,a6 drop
DO2 ROT,BASE
DO7 AT,USTAR,DPLUS,DPL,AT,ONEP,ZBRAN
dc.w PNUMB3-START
DO3 ONE,DPL,PSTORE
PNUMB3 DO2 FROMR,BRAN
dc.w PNUMB1-START
PNUMB4 DO1 FROMR
rts
WORDMX 6,NUMBE,R
NUMB DO7 ZERO,ZERO,ROT,DUP,ONEP,CAT,WLITER
dc.w $2D ; minus sign
DO5 EQUAL,DUP,TOR,PLUS,LIT
dc.l -1
NUMB1 DO8 DPL,STORE,PNUMB,DUP,CAT,BL,SUB,ZBRAN
dc.w NUMB2-START
DO3 DUP,CAT,WLITER
dc.w $2E
DO5 SUB,ZERO,QERR,ZERO,BRAN
dc.w NUMB1-START
NUMB2 addq.l #4,a6 drop
DO2 FROMR,ZBRAN
dc.w NUMB3-START
DOX DMINUS
NUMB3
rts
WORDMX 5,-FIN,D
DFIND DO9 BL,WORD,HERE,CONTXT,AT,AT,PFIND,DUP,ZEQU
DO1 ZBRAN
dc.w DFIND2-START
addq.l #4,a6 drop
DO3 HERE,LATEST,PFIND
DFIND2 rts
WORDMX 7,(ABORT,)
PABORT DOX ABORT
WORDMX 5,ERRO,R
ERROR DO4 WARN,AT,ZLESS,ZBRAN
; WARNING is -1 to abort, 0 to print error #, and >1 to pring
; error message from the message SCReen on disc
dc.w ERROR2-START
DO1 PABORT
ERROR2 DO4 HERE,COUNT,TYPE,PDOTQ
dc.b 3," ? "
DO2 MESS,SPSTOR
DOX QUIT
WORDMX 3,ID,.
IDDOT DO3 DUP,CAT,WLITER
dc.w $1F
DO3 AND,ZERO,XDO
IDDOT1 DO4 ONEP,DUP,CAT,WLITER
dc.w $7F
DO3 AND,EMIT,XLOOP
dc.w IDDOT1-START
addq.l #4,a6 drop
rts
WORDMX 6,CREAT,E
CREATE DO2 DFIND,ZBRAN
dc.w CREAT2-START
addq.l #4,a6 drop
DO1 PDOTQ
dc.b 11,"redefined: "
DO3 NFA,IDDOT,WLITER
dc.w 4
DO2 MESS,SPACE
CREAT2 DO6 HERE,DUP,DUP,CAT,OVER,WLITER
dc.w $80
DO5 TOGGLE,DUP,ROT,PLUS,WLITER
dc.w $80
DO4 TOGGLE,ONEP,WALLIGN,ALLOT
DO7 LATEST,COMMA,CURENT,AT,STORE,HERE,WLITER
dc.w $4eB9 ; JSR code
DO5 WCOMM,THREE,PLUS,THREE,PLUS
DOX COMMA
WORDMIX 9,[COMPILE,]
BCOMP DO4 DFIND,ZEQU,ZERO,QERR
addq.l #4,a6 drop
DO2 CFA,WLITER
dc.w $4eB9 PUT IN 'JSR' FIRST
DO1 WCOMM
DOX COMMA
WORDMIX 7,LITERA,L
LITER DO3 STATE,AT,ZBRAN
dc.w LITER2-START
DO3 COMPIL,LIT,COMMA
LITER2 rts
WORDMIX 8,DLITERA,L
DLITER DO3 STATE,AT,ZBRAN
dc.w DLITE2-START
DO3 COMPIL,LIT,COMMA
DLITE2 rts
WORDMX 9,INTERPRE,T
INTERP DO2 DFIND,ZBRAN
dc.w INTER5-START
DO4 DUP,STATE,AT,LESS
DO1 ZBRAN
dc.w INTER3-START
DO1 WLITER
dc.w $a0
DO2 LESS,ZBRAN
dc.w INTER1-START
DO2 CFA,WLITER
dc.w $4eb9 INSERT JSR PREFIX
DO3 WCOMM,COMMA,BRAN
dc.w INTER4-START
INTER1 DO1 CFA
INTER2 DO3 DUP,WAT,WLITER
dc.w $4e75 ; RTS code
DO2 SUB,ZBRAN
dc.w INTER21-START
DO5 DUP,WAT,WCOMM,TWOP,BRAN
dc.w INTER2-START
INTER21 addq.l #4,a6 drop
DO1 BRAN
dc.w INTER4-START
INTER3 addq.l #4,a6 drop
DO2 CFA,EXEC
INTER4 DO2 QSTACK,BRAN
dc.w INTER7-START
INTER5 DO6 HERE,NUMB,DPL,AT,ONEP,ZBRAN
dc.w INTER6-START
DO2 DLITER,BRAN
dc.w INTER7-START
INTER6 addq.l #4,a6 drop
DO1 LITER
INTER7 DO2 QSTACK,BRAN
dc.w INTERP-START
WORDMX 9,IMMEDIAT,E
IMMED DO2 LATEST,WLITER
dc.w $40
DOX TOGGLE
WORDMX 5,MACR,O
MACR DO2 LATEST,WLITER
dc.w $20
DOX TOGGLE
WORDMX 10,VOCABULAR,Y
VOCAB DO2 BUILDS,WLITER
dc.w $81A0
DO5 WCOMM,CURENT,AT,TWOM,COMMA
DO7 HERE,VOCLIN,AT,COMMA,VOCLIN,STORE,DOES
DOVOC DO2 TWOP,CONTXT
DOX STORE
WORDMX 11,DEFINITION,S
DEFIN DO3 CONTXT,AT,CURENT
DOX STORE
WORDMI1 1,,(
PAREN DO1 WLITER
dc.w $29 ; ASCII '('
DOX WORD
WORDMX 4,DUM,P
DUMP DO4 OVER,PLUS,SWAP,XDO
DUMP1 DO6 I,CR,HEX,UDOT,I,WLITER
dc.w 16
DO3 PLUS,I,XDO
DUMP2 DO6 SPACE,I,CAT,TWO,DOTR,XLOOP
dc.w DUMP2-START
DO4 THREE,SPACES,I,WLITER
dc.w 16
DO3 PLUS,I,XDO
DUMP3 DO3 I,CAT,WLITER
dc.w $7F MASK MSB
DO3 AND,DUP,WLITER
dc.w $20
DO2 LESS,ZBRAN
dc.w DUMP31-START
addq.l #4,a6 drop
DO1 WLITER
dc.w $5F ; ASCII '_'
DUMP31 DO2 EMIT,XLOOP
dc.w DUMP3-START
DO1 WLITER
dc.w 16
DO1 XPLOOP
dc.w DUMP1-START
rts
WORDMX 5,VLIS,T
VLIST DO1 WLITER
dc.w $80
DO5 OUT,STORE,CONTXT,AT,AT
VLIST1 DO5 OUT,AT,COLUMS,AT,WLITER
dc.w 16
DO3 SUB,GREAT,ZBRAN
dc.w VLIST2-START
DO4 CR,ZERO,OUT,STORE
VLIST2 DO9 DUP,IDDOT,SPACE,SPACE,PFA,LFA,AT,DUP,ZEQU
DO3 QTERM,OR,ZBRAN
dc.w VLIST1-START
addq.l #4,a6 drop
rts
WORDMX 4,QUI,T
QUIT DO4 ZERO,BLK,STORE,LBRAK
;
; Here is outer interpreter which gets line of input, does it,
; and then prints " OK" and repeats.
;
QUIT2 DO5 RPSTOR,QUIET,AT,ZEQU,ZBRAN
dc.w QUIT4-START ; no CR if in quiet mode
DO1 CR
QUIT4 DO6 QUERY,INTERP,STATE,AT,ZEQU,ZBRAN
dc.w QUIT3-START
DO4 QUIET,AT,ZEQU,ZBRAN ; no "OK" if in quiet mode
dc.w QUIT3-START
DO1 PDOTQ
dc.b 3," OK"
DO7 SPAT,SZERO,AT,SWAP,SUB,FOUR,SLASH
DO2 SPACE,DOT ; print stack depth
QUIT3 DO1 BRAN
dc.w QUIT2-START
WORDMX 5,ABOR,T
ABORT DO5 SPSTOR,DEC,DRZERO,CR,PDOTQ
dc.b 21,"Sforth68k Version 1.0"
DO6 ZERO,IN,STORE,ZERO,BLK,STORE
jsr FORTH
DO1 DEFIN
DOX QUIT
;
; insert disk words here
WORDMX 7,MESSAG,E
MESS
MESS3 DO1 PDOTQ
dc.b 6,"Error "
DO1 WLITER
dc.w $23 ; ASCII '#'
DO3 BASE,AT,WLITER
dc.w 10 ; DECIMAL
DO3 EQUAL,ZEQU,PLUS ; if = 10, add 0, if 16, add 1 to MAKE '$
DO2 EMIT,SPACE
DOX DOT
MESS4 rts
BLOCK RTS
BSCR RTS
DRZERO RTS
;
WORDMX 4,NOO,P
NOOP rts
;
; Here is stuff which gets copied to ram
; in user dictionary space
;
RAM dc.b $C5,"FORT",$80+'H' ; 5,FORT,H IMMEDIATE
dc.l NOOP-10 ; LINK "BACK" (NFA of NOOP)
RFORTH DO1 DODOES
dc.l DOVOC
dc.w $81A0
dc.l TASKAA
dc.w 0
dc.b $84,"TAS",$80+'K' ; 4,TAS,K
dc.l FORTHS ; link "back" to FORTH
RTASK rts
ERAM
;
; FORTH I/O DRIVERS
;
;
; THE NEXT WORDS ARE SYSTEM-DEPENDANT I/O SUBROUTINES
;
;
;
; NOW JUMP VECTORS FOR FORTH--3 BYTES EACH
;
PMON BRA PPMON Warmstart MON68K
PEMIT BRA PPEMIT emit char in d0.b to terminal
PKEY BRA PPKEY get char from terminal in d0.b (NO ECHO)
PQTER BRA PPQTER query terminal to see if char typed--
UCOLD RTS NAUGHT user cold start vector
UWARM RTS NAUGHT user warm start vector
;
; These i/o routines are for a signetics 2681
;
tdre equ 2
sroffs equ 1 offset to status register
rdroffs equ 3 offset to rx data register
tdroffs equ 3 offset to tx data register
serport equ $20000
rdrf equ 0 rdrf bit # in s2681
rdrfmsk equ 1 rdrf mask
* wait for character in acia
PPKEY move.l a1,-(sp)
movea.l #serport,a1 point to serport
clr.l d0 clean start
PPKEY1 btst #rdrf,sroffs(a1) rdrf?
beq.s PPKEY1 not yet
move.b rdroffs(a1),d0 yes. get character
move.l (sp)+,a1
rts
* test for character waiting
PPQTER move.l a1,-(sp)
movea.l #serport,a1 point to serport
move.b sroffs(a1),d0
andi.l #rdrfmsk,d0 rdrf?
beq.s PPQTER1 ; if not
move.b rdroffs(a1),d0 return with character
PPQTER1 move.l (sp)+,a1
rts
PPEMIT move.l a1,-(sp)
movea.l #serport,a1
bsr.s PPEMIT1 transmit char
move.l (sp)+,a1
rts
PPEMIT1 btst #tdre,sroffs(a1) tdre?
beq.s PPEMIT1 no
move.b d0,tdroffs(a1) yes, put char in tdr
rts
PPMON move.l $4,a0
jmp (a0)
END